package httpClient

import (
	"bytes"
	"context"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"net/url"
	"strings"
	"time"
)

// HTTPRequest 请求结构体
type HTTPRequest struct {
	Method  string            `json:"method"`
	URL     string            `json:"url"`
	Headers map[string]string `json:"headers"`
	Params  []HTTPParam       `json:"params"`
	Body    string            `json:"body"`
	Files   map[string]string `json:"files,omitempty"` // key: 字段名, value: base64内容
}

// HTTPParam 参数结构体
type HTTPParam struct {
	ID    int    `json:"id"`
	Key   string `json:"key"`
	Value string `json:"value"`
}

// HTTPResponse 响应结构体
type HTTPResponse struct {
	Status      int               `json:"status"`
	StatusText  string            `json:"statusText"`
	Headers     map[string]string `json:"headers"`
	Body        string            `json:"body"`
	Size        int64             `json:"size"`
	Time        int64             `json:"time"`
	ContentType string            `json:"contentType"`
	Error       string            `json:"error,omitempty"`
}

func SendRequest(request HTTPRequest, ctx context.Context) (*HTTPResponse, error) {
	// 构建URL和查询参数
	parsedURL, err := url.Parse(request.URL)
	if err != nil {
		return &HTTPResponse{Error: fmt.Sprintf("Invalid URL: %v", err)}, err
	}

	// 添加查询参数
	if len(request.Params) > 0 && (request.Method == "GET" || request.Method == "DELETE" || request.Method == "HEAD") {
		query := parsedURL.Query()
		for _, param := range request.Params {
			if param.Key != "" {
				query.Add(param.Key, param.Value)
			}
		}
		parsedURL.RawQuery = query.Encode()
	}

	// 准备请求体
	var reqBody io.Reader
	var contentType string
	// 优先处理 multipart/form-data
	if len(request.Files) > 0 {
		var b bytes.Buffer
		w := multipart.NewWriter(&b)
		// 普通字段
		for _, param := range request.Params {
			if param.Key != "" {
				_ = w.WriteField(param.Key, param.Value)
			}
		}
		// 文件字段
		for field, b64 := range request.Files {
			data, err := base64.StdEncoding.DecodeString(b64)
			if err != nil {
				return &HTTPResponse{Error: fmt.Sprintf("Failed to decode file %s: %v", field, err)}, err
			}
			fw, err := w.CreateFormFile(field, field)
			if err != nil {
				return &HTTPResponse{Error: fmt.Sprintf("Failed to create form file %s: %v", field, err)}, err
			}
			_, err = fw.Write(data)
			if err != nil {
				return &HTTPResponse{Error: fmt.Sprintf("Failed to write file %s: %v", field, err)}, err
			}
		}
		w.Close()
		reqBody = &b
		contentType = w.FormDataContentType()
	} else if request.Method != "GET" && request.Method != "HEAD" {
		if request.Body != "" {
			reqBody = strings.NewReader(request.Body)
		} else if len(request.Params) > 0 {
			// 如果没有请求体但有参数，将参数作为表单数据
			formData := url.Values{}
			for _, param := range request.Params {
				if param.Key != "" {
					formData.Add(param.Key, param.Value)
				}
			}
			reqBody = strings.NewReader(formData.Encode())
			// 如果没有设置Content-Type，设置为表单类型
			if request.Headers == nil {
				request.Headers = make(map[string]string)
			}
			if _, exists := request.Headers["Content-Type"]; !exists {
				request.Headers["Content-Type"] = "application/x-www-form-urlencoded"
			}
		}
	}

	// 创建HTTP请求
	req, err := http.NewRequestWithContext(ctx, request.Method, parsedURL.String(), reqBody)
	if err != nil {
		return &HTTPResponse{Error: fmt.Sprintf("Failed to create request: %v", err)}, err
	}

	// 添加请求头
	for key, value := range request.Headers {
		req.Header.Add(key, value)
	}
	if contentType != "" {
		req.Header.Set("Content-Type", contentType)
	}

	// 如果是JSON请求体且没有设置Content-Type，设置为JSON类型
	if request.Body != "" && strings.TrimSpace(request.Body)[0] == '{' {
		if _, exists := request.Headers["Content-Type"]; !exists {
			req.Header.Set("Content-Type", "application/json")
		}
	}

	// 创建HTTP客户端并设置超时
	client := &http.Client{
		Timeout: 30 * time.Second,
	}

	// 记录开始时间
	startTime := time.Now()

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		return &HTTPResponse{Error: fmt.Sprintf("Request failed: %v", err)}, err
	}
	defer resp.Body.Close()

	// 计算请求时间
	requestTime := time.Since(startTime).Milliseconds()

	// 读取响应体
	var bodyBuffer bytes.Buffer
	size, err := io.Copy(&bodyBuffer, resp.Body)
	if err != nil {
		return &HTTPResponse{Error: fmt.Sprintf("Failed to read response body: %v", err)}, err
	}

	// 获取响应头
	headers := make(map[string]string)
	for key, values := range resp.Header {
		headers[key] = strings.Join(values, ", ")
	}

	// 获取Content-Type
	contentType = resp.Header.Get("Content-Type")

	// 构建响应对象
	response := &HTTPResponse{
		Status:      resp.StatusCode,
		StatusText:  resp.Status,
		Headers:     headers,
		Body:        bodyBuffer.String(),
		Size:        size,
		Time:        requestTime,
		ContentType: contentType,
	}

	// 尝试格式化JSON响应
	if strings.Contains(contentType, "application/json") {
		var jsonObj any
		if err := json.Unmarshal(bodyBuffer.Bytes(), &jsonObj); err == nil {
			formattedJSON, err := json.MarshalIndent(jsonObj, "", "    ")
			if err == nil {
				response.Body = string(formattedJSON)
			}
		}
	}

	return response, nil
}
